package com.xiaoshuidi.cloud.module.guanwang.service.guanwang.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.tenant.core.context.TenantContextHolder;
import com.xiaoshuidi.cloud.module.guanwang.controller.admin.guanwang.configvo.WebsiteLinkVO;
import com.xiaoshuidi.cloud.module.guanwang.controller.admin.guanwang.vo.GuanWangConfigEditReqVO;
import com.xiaoshuidi.cloud.module.guanwang.controller.admin.guanwang.vo.GuanWangConfigListRespVO;
import com.xiaoshuidi.cloud.module.guanwang.framework.config.TenantConfiguration;
import com.xiaoshuidi.cloud.module.guanwang.framework.enums.GuanWangConfigEnum;
import com.xiaoshuidi.cloud.module.guanwang.mapper.GuanWangConfigMapper;
import com.xiaoshuidi.cloud.module.guanwang.pojo.GuanWangConfig;
import com.xiaoshuidi.cloud.module.guanwang.service.guanwang.GuanWangConfigService;
import com.xiaoshuidi.cloud.module.guanwang.service.GuanWangConfiguration;
import com.xiaoshuidi.cloud.module.iot.uitils.JSONUtil;
import com.xiaoshuidi.cloud.module.system.api.user.AdminUserApi;
import com.xiaoshuidi.cloud.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.xiaoshuidi.cloud.module.guanwang.enums.ErrorCodeConstants.CONFIG_EXISTS;
import static com.xiaoshuidi.cloud.module.guanwang.enums.ErrorCodeConstants.CONFIG_NOT_EXISTS;

@Slf4j
@Service
public class GuanWangConfigServiceImpl extends ServiceImpl<GuanWangConfigMapper, GuanWangConfig> implements GuanWangConfigService {

    @Resource
    private GuanWangConfigMapper guanWangConfigMapper;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private Validator validator;

    @Override
    public List<GuanWangConfigListRespVO> getList() {
        LambdaQueryWrapper<GuanWangConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.orderByAsc(GuanWangConfig::getIndexId);
        List<GuanWangConfig> records = list(wrapper);
        List<GuanWangConfigListRespVO> respVOS = new ArrayList<>();
        if (ObjectUtil.isEmpty(records)) {
            for (GuanWangConfigEnum configEnum : GuanWangConfigEnum.values()) {
                GuanWangConfigListRespVO respVO = new GuanWangConfigListRespVO();
                respVO.setIndexId(configEnum.getIndex());
                respVO.setItemName(configEnum.getName());
                respVOS.add(respVO);
            }
        } else {
            Map<Integer, GuanWangConfig> temp = records.stream().collect(Collectors.toMap(GuanWangConfig::getIndexId, Function.identity()));
            Set<Long> ids = records.stream().filter(p -> ObjectUtil.isNotEmpty(p.getUpdater())).map(p -> Long.valueOf(p.getUpdater())).collect(Collectors.toSet());
            Map<Long, AdminUserRespDTO> userMap = new HashMap<>();
            if (ObjectUtil.isNotEmpty(ids)) {
                userMap = adminUserApi.getUserMap(ids);
            }
            for (GuanWangConfigEnum configEnum : GuanWangConfigEnum.values()) {
                if (temp.containsKey(configEnum.getIndex())) {
                    GuanWangConfigListRespVO respVO = new GuanWangConfigListRespVO();
                    GuanWangConfig guanWangConfig = temp.get(configEnum.getIndex());
                    BeanUtil.copyProperties(guanWangConfig, respVO);
                    if (ObjectUtil.isNotEmpty(guanWangConfig.getUpdater())) {
                        AdminUserRespDTO adminUserRespDTO = userMap.get(Long.valueOf(guanWangConfig.getUpdater()));
                        respVO.setUpdaterName(adminUserRespDTO.getNickname());
                    }
                    respVOS.add(respVO);
                }else {
                    GuanWangConfigListRespVO respVO = new GuanWangConfigListRespVO();
                    respVO.setIndexId(configEnum.getIndex());
                    respVO.setItemName(configEnum.getName());
                    respVOS.add(respVO);
                }
            }
        }
        respVOS.sort(Comparator.comparing(GuanWangConfigListRespVO::getIndexId));
        return respVOS;
    }

    @Override
    public Long edit(GuanWangConfigEditReqVO reqVO) {
        // 修改
        if (ObjectUtil.isNotEmpty(reqVO.getId())) {
            GuanWangConfig guanWangConfig = guanWangConfigMapper.selectById(reqVO.getId());
            if(GuanWangConfigEnum.WEBSITE_LINK.getIndex().equals(reqVO.getIndexId())){
                WebsiteLinkVO websiteLinkVO = JSONUtil.toBean(reqVO.getConfigJson().toString(), WebsiteLinkVO.class);
                WebsiteLinkVO configJson = (WebsiteLinkVO) guanWangConfig.getConfigJson();
                log.info("[WEB官网] 更新前 域名网址->:{}", TenantConfiguration.map);
                TenantConfiguration.map.remove(configJson.getUrl());
                TenantConfiguration.map.put(websiteLinkVO.getUrl(), TenantContextHolder.getTenantId());
                log.info("[WEB官网] 更新后 域名网址->:{}", TenantConfiguration.map);
            }
            BeanUtil.copyProperties(reqVO, guanWangConfig, "configJson");
            settingConfigAndCheckParam(guanWangConfig, reqVO.getConfigJson().toString());
            guanWangConfigMapper.updateById(guanWangConfig);
            return guanWangConfig.getId();
        }
        // 新增
        GuanWangConfigListRespVO guanWangConfigListRespVO = detail(reqVO.getIndexId());
        if(ObjectUtil.isNotEmpty(guanWangConfigListRespVO.getId())){
            throw exception(CONFIG_EXISTS);
        }
        GuanWangConfig guanWangConfig = new GuanWangConfig();
        BeanUtil.copyProperties(reqVO, guanWangConfig, "configJson");
        settingConfigAndCheckParam(guanWangConfig, reqVO.getConfigJson().toString());
        guanWangConfigMapper.insert(guanWangConfig);
        if(GuanWangConfigEnum.WEBSITE_LINK.getIndex().equals(reqVO.getIndexId())){
            WebsiteLinkVO configJson = (WebsiteLinkVO) guanWangConfig.getConfigJson();
            log.info("[WEB官网] 更新前 域名网址->:{}", TenantConfiguration.map);
            TenantConfiguration.map.put(configJson.getUrl(), TenantContextHolder.getTenantId());
            log.info("[WEB官网] 更新后 域名网址->:{}", TenantConfiguration.map);

        }
        return guanWangConfig.getId();
    }

    @Override
    public GuanWangConfigListRespVO detail(Integer indexId) {
        LambdaQueryWrapper<GuanWangConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GuanWangConfig::getIndexId, indexId);
        wrapper.orderByDesc(GuanWangConfig::getCreateTime);
        wrapper.last(" limit 1");
        GuanWangConfig guanWangConfig = guanWangConfigMapper.selectOne(wrapper);
        GuanWangConfigListRespVO respVO = new GuanWangConfigListRespVO();
        BeanUtil.copyProperties(guanWangConfig, respVO);
        return respVO;
    }

    @Override
    public List<GuanWangConfigListRespVO> getListByIndexId(Integer indexId) {
        LambdaQueryWrapper<GuanWangConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GuanWangConfig::getIndexId, indexId);
        wrapper.orderByDesc(GuanWangConfig::getCreateTime);
        List<GuanWangConfig> guanWangConfigs = guanWangConfigMapper.selectList(wrapper);
        List<GuanWangConfigListRespVO> respVOS = new ArrayList<>();
        for (GuanWangConfig guanWangConfig : guanWangConfigs) {
            GuanWangConfigListRespVO respVO = new GuanWangConfigListRespVO();
            BeanUtil.copyProperties(guanWangConfig, respVO);
            respVOS.add(respVO);
        }
        return respVOS;
    }

    private void settingConfigAndCheckParam(GuanWangConfig guanWangConfig, String configStr) {
        GuanWangConfigEnum configEnum = GuanWangConfigEnum.getByIndex(guanWangConfig.getIndexId());
        Class<? extends GuanWangConfiguration> configClass = configEnum.getConfigClass();
        if (ObjectUtil.isNull(configClass)) {
            throw exception(CONFIG_NOT_EXISTS);
        }
        GuanWangConfiguration config = JSONUtil.toBean(configStr, configClass);

        // 验证参数
        config.validate(validator);
        guanWangConfig.setConfigJson(config);
        guanWangConfig.setItemName(configEnum.getName());
    }
}
